package manager;

import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.ResourceBundle;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;

import beans.ManagerPageBean;
import dtos.ManageBasicUserDTO;
import dtos.ResponseDTO;
import dtos.ResticketDTO;
import dtos.TechticketDTO;
import dtos.UserDTO;
import dtos.UserlogDTO;
import utils.Codification;
import utils.DomainDAORemote;
import utils.ResponseDAORemote;
import utils.ResticketDAORemote;
import utils.TechticketDAORemote;
import utils.UserDAORemote;
import utils.UserlogDAORemote;
import utils.UsertypeDAORemote;

/**
 * Session Bean implementation class ManageUserBean
 */
@ManagedBean
@SessionScoped
public class ManageUserBean implements Serializable {

	ResourceBundle bundle = ResourceBundle.getBundle(
			"languageSettings.language", FacesContext.getCurrentInstance()
					.getViewRoot().getLocale());

	private static final long serialVersionUID = -8496225422209810926L;
	private UserDTO modUser;
	private String username;
	private String mname;
	private String name;
	private String password;
	private String email;
	private String emailDomain;
	private String passEnding;
	private String usernameError;
	private String emailError;
	private String updateSuccessMessage;
	private String createSuccessMessage;
	private String deleteUserError;
	private String search;
	private String active;
	private String[] activeArray = { "Active", "Inactive" };
	private int domainId;
	private int isActive;
	private int idUsertype;
	private String confirmationMessage;
	private UserDTO currentUser;
	private List<ManageBasicUserDTO> listManageUserDTO;
	@EJB
	UserDAORemote udr;
	@EJB
	DomainDAORemote ddr;
	@EJB
	UsertypeDAORemote utdr;
	@EJB
	ResticketDAORemote rtdr;
	@EJB
	TechticketDAORemote ttdr;
	@EJB
	ResponseDAORemote rdr;
	@EJB
	UserlogDAORemote uldr;
	@ManagedProperty("#{managerPageBean}")
	ManagerPageBean mpb;

	/**
	 * Default constructor.
	 */
	public ManageUserBean() {
	}

	/**
	 * Initializes the necessary attributes
	 *
	 */
	@PostConstruct
	private void initialize() {
		// gets the user from the session
		
		//currentUser = udr.getUser(1);
		 currentUser = udr.getUser(((UserDTO)
		 FacesContext.getCurrentInstance()
		 .getExternalContext().getSessionMap().get("loggedUser"))
		 .getId());
		Properties prop = new Properties();
		try {
			prop.load(getClass().getResourceAsStream("/userSettings/user.properties"));
		} catch (IOException e) {
			e.printStackTrace();
		}

		setEmailDomain(prop.getProperty("emailDomain"));
		setPassEnding(prop.getProperty("passwordEnding"));
		refreshListManageUserDTO(false);
	}

	/**
	 *         Creates a new password and username for the new user in the
	 *         standard format
	 */
	private void createNewUsernameAndPassword() {
		String nUsername = this.name.toLowerCase();
		String nUsername2 = this.name;
		String tempUsername = "";
		String tempUsername2 = "";

		String[] usernameArray = nUsername.split(" ");
		String[] usernameArray2 = nUsername2.split(" ");
		if (usernameArray.length != 1) {
			tempUsername = tempUsername + usernameArray[0] + "."
					+ usernameArray[1] + ".";
			tempUsername2 = tempUsername2 + usernameArray2[0] + "."
					+ usernameArray2[1] + ".";
			tempUsername = tempUsername.substring(0, tempUsername.length() - 1);
			tempUsername2 = tempUsername2.substring(0,
					tempUsername2.length() - 1);
		} else {
			tempUsername = usernameArray[0];
			tempUsername2 = usernameArray2[0];
		}
		setEmail(tempUsername2 + this.emailDomain);
		setUsername(tempUsername);
		setPassword(tempUsername + this.passEnding);
	}

	
	
	/**
	 * @return the deleteUserError
	 */
	public String getDeleteUserError() {
		return deleteUserError;
	}

	/**
	 * @param deleteUserError the deleteUserError to set
	 */
	public void setDeleteUserError(String deleteUserError) {
		this.deleteUserError = deleteUserError;
	}

	/**
	 * @return the mpb
	 */
	public ManagerPageBean getMpb() {
		return mpb;
	}

	/**
	 * @param mpb
	 *            the mpb to set
	 */
	public void setMpb(ManagerPageBean mpb) {
		this.mpb = mpb;
	}

	/**
	 * @return the modUser
	 */
	public UserDTO getModUser() {
		return modUser;
	}

	/**
	 * @param modUser
	 *            the modUser to set
	 */
	public void setModUser(UserDTO modUser) {
		this.modUser = modUser;
	}

	/**
	 * @return the username
	 */
	public String getUsername() {
		return username;
	}

	/**
	 * @param username
	 *            the username to set
	 */
	public void setUsername(String username) {
		this.setUpdateSuccessMessage(null);
		this.username = username;
	}

	/**
	 * @return the mname
	 */
	public String getMname() {
		return mname;
	}

	/**
	 * @param mname
	 *            the mname to set
	 */
	public void setMname(String mname) {
		this.setUpdateSuccessMessage(null);
		this.mname = mname;
	}

	/**
	 * @return the password
	 */
	public String getPassword() {
		return password;
	}

	/**
	 * @param password
	 *            the password to set
	 */
	public void setPassword(String password) {
		this.password = password;
	}

	/**
	 * @return the email
	 */
	public String getEmail() {
		return email;
	}

	/**
	 * @param email
	 *            the email to set
	 */
	public void setEmail(String email) {
		this.setUpdateSuccessMessage(null);
		this.email = email;
	}

	/**
	 * @return the emailDomain
	 */
	public String getEmailDomain() {
		return emailDomain;
	}

	/**
	 * @param emailDomain
	 *            the emailDomain to set
	 */
	public void setEmailDomain(String emailDomain) {
		this.emailDomain = emailDomain;
	}

	/**
	 * @return the passEnding
	 */
	public String getPassEnding() {
		return passEnding;
	}

	/**
	 * @param passEnding
	 *            the passEnding to set
	 */
	public void setPassEnding(String passEnding) {
		this.passEnding = passEnding;
	}

	/**
	 * @return the active
	 */
	public String getActive() {
		return active;
	}

	/**
	 * @param active
	 *            the active to set
	 */
	public void setActive(String active) {
		this.setUpdateSuccessMessage(null);
		this.active = active;
	}

	/**
	 * @return the activeArray
	 */
	public String[] getActiveArray() {
		this.setUpdateSuccessMessage(null);
		return activeArray;
	}

	/**
	 * @param activeArray
	 *            the activeArray to set
	 */
	public void setActiveArray(String[] activeArray) {
		this.activeArray = activeArray;
	}

	/**
	 * @return the domainId
	 */
	public int getDomainId() {
		return domainId;
	}

	/**
	 * @param domainId
	 *            the domainId to set
	 */
	public void setDomainId(int domainId) {
		this.domainId = domainId;
	}

	/**
	 * @return the isActive
	 */
	public int getIsActive() {
		return isActive;
	}

	/**
	 * @param isActive
	 *            the isActive to set
	 */
	public void setIsActive(int isActive) {
		this.isActive = isActive;
	}

	/**
	 * @return the idUsertype
	 */
	public int getIdUsertype() {
		return idUsertype;
	}

	/**
	 * @param idUsertype
	 *            the idUsertype to set
	 */
	public void setIdUsertype(int idUsertype) {
		this.idUsertype = idUsertype;
	}

	/**
	 * @return the currentUser
	 */
	public UserDTO getCurrentUser() {
		return currentUser;
	}

	/**
	 * @param currentUser
	 *            the currentUser to set
	 */
	public void setCurrentUser(UserDTO currentUser) {
		this.currentUser = currentUser;
	}

	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}

	/**
	 * @return the search
	 */
	public String getSearch() {
		return search;
	}

	/**
	 * @param search
	 *            the search to set
	 */
	public void setSearch(String search) {
		this.setDeleteUserError(null);
		this.search = search;
	}

	/**
	 * @return the updateSuccessMessage
	 */
	public String getUpdateSuccessMessage() {
		return updateSuccessMessage;
	}

	/**
	 * @param updateSuccessMessage
	 *            the updateSuccessMessage to set
	 */
	public void setUpdateSuccessMessage(String updateSuccessMessage) {
		this.updateSuccessMessage = updateSuccessMessage;
	}

	/**
	 * @return the emailError
	 */
	public String getEmailError() {
		return emailError;
	}

	/**
	 * @param emailError
	 *            the emailError to set
	 */
	public void setEmailError(String emailError) {
		this.emailError = emailError;
	}

	/**
	 * @return the usernameError
	 */
	public String getUsernameError() {
		return usernameError;
	}

	/**
	 * @param usernameError
	 *            the usernameError to set
	 */
	public void setUsernameError(String usernameError) {
		this.usernameError = usernameError;
	}

	/**
	 * When the name of the new user is changed, the method calls the
	 * createNewUsernameAndPassword() method
	 * 
	 * @param name
	 * 
	 */
	public void setName(String name) {
		this.name = name;
		if (name != null) {
			createNewUsernameAndPassword();
		}
	}

	/**
	 * @return the confirmationMessage
	 */
	public String getConfirmationMessage() {
		return confirmationMessage;
	}

	/**
	 * @param confirmationMessage
	 *            the confirmationMessage to set
	 */
	public void setConfirmationMessage(String confirmationMessage) {
		this.confirmationMessage = confirmationMessage;
	}

	/**
	 * @return the createSuccessMessage
	 */
	public String getCreateSuccessMessage() {
		return createSuccessMessage;
	}

	/**
	 * @param createSuccessMessage
	 *            the createSuccessMessage to set
	 */
	public void setCreateSuccessMessage(String createSuccessMessage) {
		this.createSuccessMessage = createSuccessMessage;
	}

	/**
	 * @return the listManageUserDTO
	 */
	public List<ManageBasicUserDTO> getListManageUserDTO() {
		return listManageUserDTO;
	}

	/**
	 * the listManageUserDTO to set
	 * 
	 * @param listManageUserDTO
	 * 
	 */
	public void setListManageUserDTO(List<ManageBasicUserDTO> listManageUserDTO) {
		this.listManageUserDTO = listManageUserDTO;
	}

	/**
	 * Listener for the create new user button, creates a new user, sends, the
	 * new user to the UserDAO and resets the user parameters.
	 * 
	 * @param event
	 * 
	 */

	public void createUserActionListener(ActionEvent event) {

		UserDTO newUser = new UserDTO();
		newUser.setEmail(this.email);
		newUser.setIdDomain(this.currentUser.getIdDomain());
		newUser.setIdUsertype(4);
		newUser.setIsActive(1);
		newUser.setName(this.name);
		newUser.setPassword(new Codification().md5(password));
		newUser.setUsername(this.username);
		udr.insertUser(newUser);
		this.setCreateSuccessMessage(bundle.getString("OM_manageUserBean_successMessage"));
		this.name = null;
		this.email = null;
		this.username = null;
		this.password = null;

	}

	/**
	 * Action Listener for the delete button in the CRUD users page
	 * 
	 * @param event
	 * 
	 */
	public void deleteUserListener(ActionEvent event) {
		int id = Integer.valueOf(event.getComponent().getAttributes()
				.get("userid").toString());
		modUser = udr.getUser(id);
		this.deleteUser();
	}

	/**
	 * Action Listener for the Edit button in the CRUD users page
	 * 
	 * @param event
	 * 
	 */
	public void editUserListener(ActionEvent event) {
		int id = Integer.valueOf(event.getComponent().getAttributes()
				.get("userid").toString());
		modUser = udr.getUser(id);
		System.out.println(modUser.getName());
		System.out.println(id);
		this.goToEdit(modUser);
	}

	/**
	 * Inserts into the fields the data of the user, to be updated, and
	 * redirects to the edit basic user page
	 * 
	 * @return The page name of the edit basic users page
	 */
	public void goToEdit(UserDTO mUser) {
		System.out.println(mUser.getName());
		this.setUpdateSuccessMessage(null);
		this.setMname(mUser.getName());
		this.setUsername(mUser.getUsername());
		this.setEmail(mUser.getEmail());
		this.setIsActive(mUser.getIsActive());
		this.setPassword(mUser.getPassword());
		if (mUser.getIsActive() == 0) {
			this.setActive("Inactive");
		} else {
			this.setActive("Active");
		}
		System.out.println(this.getMname());
		mpb.setPage("editUser");
	}

	/**
	 * Returns false if the mail is already used by an other user, true, if the
	 * mail is not used, or the mail is of the user, for which we are checking
	 * for.
	 * 
	 * @return true or false
	 */
	public boolean checkMailDuplicate() {
		UserDTO verUser = udr.getUserDTOByEmail(this.getEmail());
		if (verUser != null) {
			if (verUser.getEmail().equals(this.getEmail())
					&& verUser.getId() == modUser.getId()) {
				this.setEmailError(null);
				return true;
			} else {
				this.setEmailError(bundle
						.getString("Beans_manager_manageUserBean_msgDuplicateEmail"));
				return false;
			}
		} else {
			this.setEmailError(null);
			return true;
		}
	}

	/**
	 * Returns false if the username is already used by an other user, true, if
	 * the username is not used, or the username is of the user, for which we
	 * are checking for.
	 * 
	 * @return true or false
	 */
	public boolean checkUsernameDuplicate() {
		List<UserDTO> verUser = udr.getAllUsersByUsername(this.getUsername());
		for (UserDTO us : verUser) {
			if (us.getUsername().equals(this.getUsername())
					&& us.getId() == modUser.getId()) {
				this.setUsernameError(null);

			} else {
				this.setUsernameError(bundle.getString("OM_menageUserBean_duplUsername"));
			}
		}
		if (this.getUsernameError() == null) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * Action Listener for the update user button in the update basic user page
	 * 
	 * @param event
	 * 
	 */
	public void updateUserListener(ActionEvent event) {
		this.setUpdateSuccessMessage(null);
		if (checkMailDuplicate() && checkUsernameDuplicate()) {
			if (getActive().equals("Active")) {
				modUser.setIsActive(1);
			} else {
				modUser.setIsActive(0);
			}
			modUser.setEmail(this.getEmail());
			modUser.setName(this.getMname());
			modUser.setUsername(this.getUsername());
			udr.updateUser(modUser);
			this.refreshListManageUserDTO(false);
			this.setUpdateSuccessMessage(bundle.getString("OM_editUser_successMessage"));
			this.setEmailError(null);
			this.setUsernameError(null);
		}

	}

	/**
	 * Resets the fields used to update the user, and redirects the page to the
	 * CRUD users page
	 * 
	 * @return The page name of the CRUD users page
	 */
	public void goToUsers(ActionEvent event) {
		this.setCreateSuccessMessage(null);
		this.setMname(null);
		this.setUsername(null);
		this.setEmail(null);
		this.setName(null);
		this.refreshListManageUserDTO(false);
		mpb.setPage("addUser");

	}

	/**
	 * Resets the fields used to update the user, and redirects the page to the
	 * CRUD users page
	 * 
	 * @return The page name of the CRUD users page
	 */
	public void goBackToUsers(ActionEvent event) {
		this.setUpdateSuccessMessage(null);
		this.setDeleteUserError(null);
		this.setMname(null);
		this.setUsername(null);
		this.setEmail(null);
		this.setName(null);
		this.refreshListManageUserDTO(false);
		mpb.setPage("manageUsers");
	}

	/**
	 * Resets the password of the user to the default password
	 * 
	 * @return The edit basic user page
	 */
	public void resetPasswordListener(ActionEvent event) {
		String nUsername = modUser.getName().toLowerCase();
		String tempUsername = "";

		String[] usernameArray = nUsername.split(" ");
		if (usernameArray.length != 1) {
			tempUsername = tempUsername + usernameArray[0] + "."
					+ usernameArray[1] + ".";
			tempUsername = tempUsername.substring(0, tempUsername.length() - 1);
		} else {
			tempUsername = usernameArray[0];
		}
		setPassword(tempUsername + this.passEnding);
		modUser.setPassword(new Codification().md5(tempUsername
				+ this.passEnding));
		udr.updateUser(modUser);
		this.setUpdateSuccessMessage(bundle.getString("OM_editUser_successMessage2"));

	}

	/**
	 * Inserts into the fields the data of the user, to be updated, and
	 * redirects to the edit basic user page
	 * 
	 * @return The page name of the edit basic users page
	 */
	public void goToEdit() {
		this.setUpdateSuccessMessage(null);
		setMname(modUser.getName());
		setUsername(modUser.getUsername());
		setEmail(modUser.getEmail());
		setIsActive(modUser.getIsActive());
		setPassword(modUser.getPassword());
		if (modUser.getIsActive() == 0) {
			setActive("Inactive");
		} else {
			setActive("Active");
		}

		mpb.setPage("editUser");
	}

	private boolean checkDeleteUser() {
		List<ResticketDTO> resTickets = rtdr.getResticketsByUser(modUser);
		List<TechticketDTO> techTickets = ttdr.getTechticketsByUser(modUser);
		List<ResponseDTO> answers = rdr
				.getAllResponsesByUserId(modUser.getId());
		List<UserlogDTO> logs = uldr.getAllUserlogsByUserId(modUser.getId());
		List<UserDTO> users = udr.getAllUsersDTO();
		boolean canDelete = true;
		if (!resTickets.isEmpty()) {
			canDelete = false;
		}
		if (!techTickets.isEmpty()) {
			canDelete = false;
		}
		if (!answers.isEmpty()) {
			canDelete = false;
		}
		if (!logs.isEmpty()) {
			canDelete = false;
		}
		for (UserDTO user : users) {
			if (user.getIdUser() == modUser.getId()) {
				canDelete = false;
			}
		}

		return canDelete;
	}

	/**
	 * Deletes the user and the corresponding tickets, answers and logs of the
	 * user
	 * 
	 * @return The name of the CRUD users page
	 */
	public void deleteUser() {

		if (checkDeleteUser()) {
			this.setConfirmationMessage("The user was deleted successfully!");
			this.setDeleteUserError(null);
			udr.deleteUser(modUser);
		} else {
			this.setDeleteUserError(bundle.getString("OM_menageUserBean_cantDel"));
			this.setConfirmationMessage(null);
		}
		refreshListManageUserDTO(true);

		mpb.setPage("manageUsers");
	}

	/**
	 * Refreshes the list of the basic users form a specific domain to perform
	 * CRUD operations on
	 * 
	 */
	public void refreshListManageUserDTO(boolean fromDelete) {

		if (!fromDelete) {
			this.setConfirmationMessage(null);
			this.setDeleteUserError(null);
		}
		if(fromDelete && this.getConfirmationMessage()!=null){
			this.setDeleteUserError(null);
		}
		this.setUpdateSuccessMessage(null);
		List<UserDTO> listUserDTO = udr.getUsersByDomainandUsertype(
				currentUser.getIdDomain(), 4);
		List<ManageBasicUserDTO> listManageBasicUserDTO = new ArrayList<>();
		for (UserDTO us : listUserDTO) {
			ManageBasicUserDTO mus = new ManageBasicUserDTO();
			if (us.getIsActive() == 1) {
				mus.setActive("Active");
			} else {
				mus.setActive("Inactive");
			}
			mus.setDomain(ddr.getDomain(us.getIdDomain()).getName());
			mus.setEmail(us.getEmail());
			mus.setName(us.getName());
			mus.setUserId(us.getId());
			mus.setUsername(us.getUsername());
			mus.setUsertype(utdr.getUsertype(us.getIdUsertype()).getName());
			listManageBasicUserDTO.add(mus);
		}
		setListManageUserDTO(listManageBasicUserDTO);
	}

	/**
	 * Removes from the users list whose name does not contain the value
	 * inserted into the search field
	 */
	public void orderUsers() {
		int i = 0;
		if (search.length() < 1)
			return;
		while (i < listManageUserDTO.size()) {
			if (!listManageUserDTO.get(i).getName().toUpperCase()
					.contains(search.toUpperCase())) {
				listManageUserDTO.remove(i);
			} else {
				i++;
			}
		}

	}

	public void resetMessages(){
		this.setConfirmationMessage(null);
		this.setDeleteUserError(null);
	}
	
	/**
	 * Listener for the search field, refreshes the list of the basic users to
	 * be shows on the page, and calls the orderUsers method to filter these
	 * users
	 */
	public void searchUsers() {
		this.resetMessages();
		this.refreshListManageUserDTO(false);
		orderUsers();
	}

}
